package com.nervenets.web.controller.handler.admin.movie;

import com.nervenets.utils.StringUtils;
import com.nervenets.web.controller.handler.SessionHandler;
import com.nervenets.web.enumeration.*;
import com.nervenets.web.hibernate.domain.film.Movie;
import com.nervenets.web.hibernate.domain.film.MovieCheckChange;
import com.nervenets.web.hibernate.domain.film.MoviePriceChange;
import com.nervenets.web.hibernate.domain.film.MovieStatusChange;
import com.nervenets.web.redis.domain.user.UserStored;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class MovieListForManagerHandler extends SessionHandler<MovieListForManagerParams> {
    @Override
    public ArrayList<Role> allowRoles() {
        return Role.issues();
    }

    @Override
    public boolean needLog() {
        return false;
    }

    @Override
    public String handle(MovieListForManagerParams params, HttpServletRequest request) throws Exception {
        String hql = "from Movie where id > 0 ";
        List<Object> objects = new ArrayList<>();

        if (null != params.getType()) {
            hql += "and type = ? ";
            objects.add(params.getType());
        }

        if (null != params.getStatus()) {
            hql += "and status = ? ";
            objects.add(params.getStatus());
        }

        if (null != params.getReleaseStatus()) {
            hql += "and releaseStatus = ? ";
            objects.add(params.getReleaseStatus());
        }

        if (!StringUtils.isEmpty(params.getKeyword())) {
            hql += "and info like ? ";
            objects.add("%" + params.getKeyword() + "%");
        }

        if (1 == params.getChecking()) {
            hql += "and checkInfo like '%\"status\":\"checking\"%' ";
        } else if (2 == params.getChecking()) {
            hql += "and checkInfo like '%\"status\":\"failed\"%' ";
        }

        final UserStored user = globalService.getUser(params.getUserId());
        if (!user.getRole().isAdmin()) {
            hql += "and userId = ? ";
            objects.add(params.getUserId());
        }

        final BigDecimal countOfByHql = userDao.getCountOfByHql(hql, objects);
        hql += "order by queue desc ";
        final List<Movie> movies = userDao.getAllObjectsByHql(hql, objects, params.getStart(), params.getLimit());
        HashMap<Long, UserStored> userStoredHashMap = new HashMap<>();
        List<Model> models = new ArrayList<>();
        for (Movie movie : movies) {
            models.add(new Model(movie, globalService.getMovieBuyMoney(movie.getId())));
            if (!userStoredHashMap.containsKey(movie.getUserId())) {
                userStoredHashMap.put(movie.getUserId(), globalService.getUser(movie.getUserId()));
            }
        }

        return successMessage(models,
                new KeyValue("start", params.getStart()),
                new KeyValue("total", countOfByHql.intValue()),
                new KeyValue("users", userStoredHashMap)
        );
    }

    @Override
    public String result() throws Exception {
        return successMessage(new Model());
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    class Model {
        private int createTime;
        private long movieId;
        private String title;
        private String coverImage;
        private long userId;
        private long priceOfUnit;
        private int userLimit;
        private MovieType type;
        private MovieStatus status;
        private MovieReleaseStatus releaseStatus;
        private List<MoviePriceChange> priceChanges;
        private List<MovieStatusChange> statusChanges;
        private List<MovieCheckChange> checkChanges;
        private long totalOfMoney;
        private long salesOfMoney;
        private boolean checking;
        private boolean checkFailed;
        private String failedReason;

        private BigDecimal profit;
        private boolean profitChecking;
        private String profitFailedReason;

        public Model(Movie movie, long salesOfMoney) {
            this.createTime = movie.getCreateTime();
            this.movieId = movie.getId();
            this.title = movie.getTitle();
            this.coverImage = movie.getCoverImage();
            this.userId = movie.getUserId();
            this.priceOfUnit = movie.getPriceOfUnit();
            this.userLimit = movie.getUserLimit();
            this.type = movie.getType();
            this.status = movie.getStatus();
            this.releaseStatus = movie.getReleaseStatus();
            this.priceChanges = movie.getPriceChanges();
            this.statusChanges = movie.getStatusChanges();
            this.checkChanges = movie.getCheckChanges();
            this.totalOfMoney = movie.getTotalOfMoney();
            this.salesOfMoney = salesOfMoney;
            this.checking = null != movie.getCheckInfo();
            if (this.checking) {
                this.checkFailed = MovieInfoStatus.failed.equals(movie.getCheckInfo().getStatus());
                this.failedReason = movie.getCheckInfo().getFailedReason();
            }

            this.profit = movie.getInfo().getProfit();
            this.profitChecking = MovieStatus.bonus.equals(movie.getStatus()) && null != movie.getInfo().getProfit() && StringUtils.isEmpty(movie.getInfo().getProfitFailedReason());
            this.profitFailedReason = movie.getInfo().getProfitFailedReason();
        }
    }
}
